#ifndef _UTILS_H_
#define _UTILS_H_


#include <buildspec.h>
#include <sstream>
#include <string>
#include <vector>
#include <Geometry/IFileSerialisable.h>
#include <Client/ClientUtils/MoMaStructs.h>
#include <Client/ClientUtils/Network/TableAttributeDesc.h>
#include <Client/ClientUtils/Network/ObjectPropertyDesc.h>
#include <Client/ClientUtils/Network/SimplexPropertyDesc.h>
#include <Client/ClientUtils/Network/FeatureClassDetailedDesc.h>
#include <Utils/Color.h>

#include <boost/optional.hpp>

namespace GST
{
namespace ClientUtils
{
	
GST_API_EXPORT std::string& strreplace(std::string& in, const std::string& from, const std::string& to);
GST_API_EXPORT bool stringInVector( const std::string & toFind, const std::vector<std::string> & findin, bool case_sensitive=true );
GST_API_EXPORT std::vector<std::string>::iterator getStringInVector( const std::string & toFind, std::vector<std::string> & findin, bool case_sensitive=true );

GST_API_EXPORT bool IsDefaultProperty( const std::string & name) ;

GST_API_EXPORT ClientUtils::OwnerList::const_iterator GetOwnerById(const OwnerList & from, Owner::OwnerId id);
GST_API_EXPORT ClientUtils::ColorScaleList::iterator GetColorScaleById( ColorScaleList & from, ColorScale::ColorScaleId id );
GST_API_EXPORT ClientUtils::ColorValueList::const_iterator GetColorValueById(const ColorValueList & from, ColorValue::ColorValueId id );
/**
  * @returns A TableAttributeDescListPtr from ObjectPropertyList
  * when corresponding object property is called "id", TableAttributekeyDesc with primary key flag will be created instead of TableAttributeDesc.    */

GST_API_EXPORT ClientUtils::TableAttributeDescListPtr ObjectPropertyDescListPtrToTableAttributeDescListPtr(ObjectPropertyDescListPtr objectProperties);
GST_API_EXPORT ClientUtils::TableAttributeDescListPtr SimplexPropertyDescListPtrToTableAttributeDescListPtr(SimplexPropertyDescListPtr simplexProperties);


GST_API_EXPORT ClientUtils::ObjectPropertyDescListPtr TableAttributeDescListPtrToObjectPropertyDescListPtr(TableAttributeDescListPtr properties);
GST_API_EXPORT ClientUtils::SimplexPropertyDescListPtr TableAttributeDescListPtrToSimplexPropertyDescListPtr(TableAttributeDescListPtr properties, GST::Geometry::PropertyAlignments alignment = GST::Geometry::VERTEX_ALIGNED);

GST_API_EXPORT ClientUtils::ObjectPropertyDescArrayPtr ObjectPropertyDescListPtrToObjectPropertyDescArrayPtr(ObjectPropertyDescListPtr objProperties);
GST_API_EXPORT ClientUtils::SimplexPropertyDescArrayPtr SimplexPropertyDescListPtrToSimplexPropertyDescArrayPtr(SimplexPropertyDescListPtr simplexProperties);

GST_API_EXPORT TableAttributeKeyDescListPtr TableAttributeDescList2TableAttributeKeyDescList( const TableAttributeDescList & descList);
GST_API_EXPORT TableAttributeDescListPtr TableAttributeKeyDescList2TableAttributeDescList( const TableAttributeKeyDescList & keyList);

GST_API_EXPORT void ParseTablename(const std::string& tablename, std::string& table, std::string& schema, std::string& db, bool removeQuotes=true);
GST_API_EXPORT void ParseColumnname(const std::string& columnname, std::string& column, std::string& table, std::string& schema, std::string& db, bool removeQuotes=true);
GST_API_EXPORT std::string RemoveQuotes( const std::string & identifer );
GST_API_EXPORT std::string ReplaceSchema( const std::string & fulltableName, const std::string & newSchemaname );

/**
  * @returns A TableAttributeValWithKeyPtr from cp_values where the given primary key (keyValues) are matching
  * This is similar to the where clause of statement (in pseudo code):
  * select cp_values.* from cp_values where cp_values.pk1 = keyValues.pk1 AND cp_values.pk2 = keyValues.2
  *
  * @throws exceptions::GSTRuntimeException		If no matching key pair found
  * @throws exceptions::KeyIsNull				If a key value in keyValues is a NULL value (thrown from TableAttributeValWithKey::compareKeyValues)
  */
GST_API_EXPORT ConstrainedTableAttributeValPtr GetConstrainedValueByKey(ClientUtils::ConstrainedTableAttributeValArrayPtr cp_values, const ClientUtils::TableAttributeValueArray & keyValues);
GST_API_EXPORT bool IsInvalidUserName(const std::string &name);
GST_API_EXPORT bool IsInvalidGroupName(const std::string &name);

// Returns the name, if it is present and not NULL and not empty.
GST_API_EXPORT boost::optional<std::string> GetNameFromObjectPropertyValues(
	const TableAttributeValList &values);
// Returns the color, if it is present and not NULL.
GST_API_EXPORT boost::optional<Utils::ColorRGBA>
GetColorFromObjectPropertyValues(const TableAttributeValList &values);
// Returns the alias, if it is present and not NULL and not empty.
GST_API_EXPORT boost::optional<std::string> GetAliasFromObjectPropertyValues(
	const TableAttributeValList &values);

// Convertsion between `PropertyTypes` and `TableAttributeDesc::DType`
GST_API_EXPORT TableAttributeDesc::DType attributeTypeFromPropertyType(
	Geometry::PropertyTypes propertyType);
GST_API_EXPORT Geometry::PropertyTypes propertyTypeFromAttributeType(
	TableAttributeDesc::DType propertyType);

// Returns the next free name in the given list of names
//
// The name is generated using the pattern "<left><counter><right>", where
// counter is a increasing integer, starting from 1.
//
// This function will find the next free gap given the input pattern.
//
// Example:
//
// nextFreeName("test(", ")", {"test(1)", "ok", "test(3)"}) == "test(2)"
// nextFreeName("test(", ")", {}) == "test(1)"
// nextFreeName("test(", ")", {"ok"}) == "test(1)"
// nextFreeName("test(", ")", {"test(1)"}) == "test(2)"
GST_API_EXPORT std::string nextFreeName(const std::string &left,
										const std::string &right,
										const std::vector<std::string> &names);

} // namespace ClientUtils
} // namespace GST

#endif
